package cn.accjiyun.gomoku.engine;

import cn.accjiyun.gomoku.MainApp;
import cn.accjiyun.gomoku.model.ChessPoint;
import cn.accjiyun.gomoku.model.PointValue;
import cn.accjiyun.gomoku.model.Role;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import static javafx.scene.input.KeyCode.X;

/**
 * Created by jiyun on 2016/9/17.
 */
public class Evaluate {

    private static int boardSize;
    private int[][] forecastChessboard;
    private Stack<ChessPoint> chessStack;
    private int nowPlayer;
    private List<PointValue> possibleMoveChess = new ArrayList<>();
    private int[][][][] chessPointStyle;
    private int[][][] score;
    private int[][] pointScore;
    private int[] scope = new int[5];
    private boolean[][] isCompute;

    public List<PointValue> getPossibleMoveChess() {
        return possibleMoveChess;
    }

    public Evaluate(GomokuAI gomokuAI) {
        boardSize = gomokuAI.getBoardSize();
        forecastChessboard  = new int[boardSize + 5][boardSize + 5];
        chessPointStyle = new int[3][boardSize + 5][boardSize + 5][4];
        score = new int[3][boardSize + 5][boardSize + 5];
        pointScore = new int[boardSize + 5][boardSize + 5];

        chessStack = gomokuAI.getChessStack();
        updateForecastBoard();
        int half = boardSize / 2 + 1;
        for (int i = 1; i <= boardSize; i++) {
            for (int j = 1; j <= boardSize; j++) {
                int distance = Math.abs(i - half) > Math.abs(j - half) ? Math.abs(i - half) : Math.abs(j - half);
                pointScore[i][j] = boardSize / 2 - distance;
            }
        }
        nowPlayer = 3 - chessStack.peek().getRole();
        setScope();
        chessModel();
        SetPointScore();
    }

    public void updateForecastBoard() {
        for (ChessPoint chessPoint : chessStack) {
            forecastChessboard[chessPoint.getX()][chessPoint.getY()] = chessPoint.getRole();
        }
    }

    public int complexionWeigh() {
        int sumScore = 0;
        int maxBackScore = 0;
        int maxWhiteScore = 0;
        for (int pointY = scope[2]; pointY < scope[4]; pointY++) {
            for (int pointX = scope[1]; pointX < scope[3]; pointX++) {
                if (maxBackScore < pointScore[pointX][pointY]) {
                    maxBackScore = pointScore[pointX][pointY];
                }
                if (maxWhiteScore < pointScore[pointX][pointY]) {
                    maxWhiteScore = pointScore[pointX][pointY];
                }
                sumScore += pointScore[pointX][pointY];
            }
        }
        return sumScore;
    }

    public void SetPointScore() {
        for (int pointY = scope[2]; pointY <= scope[4]; pointY++) {
            for (int pointX = scope[1]; pointX <= scope[3]; pointX++) {
                if (isCompute[pointX][pointY] == false) continue;
                for (int color = Role.BLACK; color <= Role.WHITE; color++) {
                    for (int dir = 0; dir < 4; dir++) {
                        score[color][pointX][pointY] += chessPointStyle[color][pointX][pointY][dir];
                    }
                }
                pointScore[pointX][pointY] +=
                        score[nowPlayer][pointX][pointY] - score[3 -nowPlayer][pointX][pointY];
                PointValue pointValue = new PointValue();
                pointValue.setX(pointX);
                pointValue.setY(pointY);
                pointValue.setRole(nowPlayer);
                pointValue.setValue(score[nowPlayer][pointX][pointY] + score[3 -nowPlayer][pointX][pointY]);
                possibleMoveChess.add(pointValue);
            }
        }
    }

    public void chessModel() {

        for (int pointY = scope[2]; pointY <= scope[4]; pointY++) {
            for (int pointX = scope[1]; pointX <= scope[3]; pointX++) {
                for (int color = Role.BLACK; color <= Role.WHITE; color++) {
                    if (isCompute[pointX][pointY] == false) continue;
                    if (forecastChessboard[pointX][pointY] == 0) {
                        forecastChessboard[pointX][pointY] = color;

                        int contiue = 0, colorNumber = 0, blank = 0, gap = 0, lenth = 1, tempLenth, i;
                        boolean isContinue = true, isLenthEnd = false, left = false, right = false; //是否连续，是否开放


                        /**
                         * 横向检测
                         */
                        for(i = 0; i <= 4 && pointX - i > 0 ; i++){   //向左检查

                            if (forecastChessboard[pointX - i][pointY] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX - i - 1 > 0 && forecastChessboard[pointX - i - 1][pointY] == 0){
                                        left = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX - i][pointY] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX-i - 1 <= 0) {  //边界情况
                                    left = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX - i - 1][pointY] != color) {
                                    left = true;
                                    if (forecastChessboard[pointX - i - 2][pointY] != color || i + 2 > 4){
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            }else if (forecastChessboard[pointX - i][pointY] == 3 - color){
                                lenth += i - 1;
                                break;
                            }
                        }
                        tempLenth = lenth;
                        for (i = 1; i < tempLenth; i++) {
                            if (forecastChessboard[pointX - i][pointY] == 0) {
                                gap++;
                            }
                        }
                        isContinue = true;
                        isLenthEnd = false;

                        for(i = 0; i <= 4 && pointX + i <= boardSize; i++){             //向右检查
                            if (forecastChessboard[pointX + i][pointY] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX + i + 1 <= boardSize && forecastChessboard[pointX + i + 1][pointY] == 0){
                                        right = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX + i][pointY] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX+ i + 1 > 15) {  //边界情况
                                    right = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX + i + 1][pointY] != color) {
                                    right = true;
                                    if (forecastChessboard[pointX + i + 2][pointY] != color || i + 2 > 4) {
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX + i][pointY] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        for (i = 1; i < lenth - tempLenth; i++) {
                            if (forecastChessboard[pointX + i][pointY] == 0) {
                                gap++;
                            }
                        }
                        setChessPointStyle(color, pointX, pointY, 0, contiue - 1, colorNumber - 1, blank, gap, lenth, left, right);
                        /**
                         *   "\"斜检测
                         */
                        isContinue = true;
                        left = right = isLenthEnd = false;
                        contiue = colorNumber = blank = gap = 0;
                        lenth = 1;
                        for(i = 0; i <= 4 && pointX + i<= boardSize && pointY + i <= boardSize; i++){ //向右下检查
                            if (forecastChessboard[pointX+i][pointY+i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX + i + 1<= boardSize && pointY + i + 1<= boardSize
                                            && forecastChessboard[pointX+i + 1][pointY+i + 1] == 0){
                                        left = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX+i][pointY+i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX+i + 1 > 15 || pointY+i +1 > 15) {  //边界情况
                                    left = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX + i + 1][pointY+i + 1] != color) {
                                    left = true;
                                    if (forecastChessboard[pointX + i + 2][pointY+i + 2] != color || i + 2 > 4) {
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX+i][pointY+i] == 3 - color){
                                lenth += i - 1;
                                break;
                            }
                        }
                        tempLenth = lenth;
                        for (i = 1; i < tempLenth; i++) {
                            if (forecastChessboard[pointX+i][pointY+i] == 0) {
                                gap++;
                            }
                        }
                        isContinue = true;
                        isLenthEnd = false;
                        for(i = 0; i <= 4 && pointX - i > 0 && pointY - i > 0; i++){ //向左上检查
                            if (forecastChessboard[pointX-i][pointY-i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX - i - 1> 0 && pointY - i - 1 > 0
                                            && forecastChessboard[pointX-i - 1][pointY-i - 1] == 0){
                                        right = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX-i][pointY-i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX-i - 1 <= 0 || pointY-i -1 <= 0) {  //边界情况
                                    right = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX-i - 1][pointY-i - 1] != color) {
                                    right = true;
                                    if (forecastChessboard[pointX-i - 2][pointY-i - 2] != color || i + 2 > 4) {
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX-i][pointY-i] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        for (i = 1; i < lenth - tempLenth; i++) {
                            if (forecastChessboard[pointX-i][pointY-i] == 0) {
                                gap++;
                            }
                        }
                        setChessPointStyle(color, pointX, pointY, 1, contiue - 1, colorNumber - 1, blank, gap, lenth, left, right);

                        /**
                         * 纵向检测
                         */

                        isContinue = true;
                        left = right = isLenthEnd = false;
                        contiue = colorNumber = blank = gap = 0;
                        lenth = 1;
                        for(i = 0; i <= 4 && pointY + i <= boardSize; i++){ //向下检查
                            if (forecastChessboard[pointX][pointY + i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointY + i + 1 <= boardSize && forecastChessboard[pointX][pointY + i + 1] == 0){
                                        left = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX][pointY + i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointY + i + 1 > 15) {  //边界情况
                                    left = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX][pointY + i + 1] != color) {
                                    left = true;
                                    if (forecastChessboard[pointX][pointY + i + 2] != color || i + 2 > 4) {
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX][pointY + i] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        tempLenth = lenth;
                        for (i = 1; i < tempLenth; i++) {
                            if (forecastChessboard[pointX][pointY + i] == 0) {
                                gap++;
                            }
                        }
                        isContinue = true;
                        isLenthEnd = false;
                        for(i = 0; i <= 4 && pointY - i> 0; i++){ //向上检查
                            if (forecastChessboard[pointX][pointY - i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointY - i - 1> 0 && forecastChessboard[pointX][pointY - i - 1] == 0){
                                        right = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX][pointY - i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointY-i -1 <= 0) {  //边界情况
                                    right = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX][pointY - i - 1] != color) {
                                    right = true;
                                    if (forecastChessboard[pointX][pointY - i - 2] != color || i + 2 > 4){
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            }else if (forecastChessboard[pointX][pointY - i ] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        for (i = 1; i < lenth - tempLenth; i++) {
                            if (forecastChessboard[pointX][pointY - i] == 0) {
                                gap++;
                            }
                        }
                        setChessPointStyle(color, pointX, pointY, 2, contiue - 1, colorNumber - 1, blank, gap, lenth, left, right);

                        /**
                         *   "/"斜检测
                         */
                        isContinue = true;
                        left = right = isLenthEnd = false;
                        contiue = colorNumber = blank = gap = 0;
                        lenth = 1;
                        for(i = 0; i <= 4 && pointX + i <= boardSize && pointY - i > 0; i++){ //向右上检查
                            if (forecastChessboard[pointX+i][pointY-i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX + i + 1 <= boardSize && pointY - i - 1 > 0
                                            && forecastChessboard[pointX + i + 1][pointY-i - 1] == 0){
                                        left = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX+i][pointY-i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX + i + 1 > 15 || pointY-i -1 <= 0) {  //边界情况
                                    left = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX+i + 1][pointY-i - 1] != color) {
                                    left = true;
                                    if (forecastChessboard[pointX+i + 2][pointY-i - 2] != color || i + 2 > 4){
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX+i][pointY-i] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        tempLenth = lenth;
                        for (i = 1; i < tempLenth; i++) {
                            if (forecastChessboard[pointX+i][pointY-i] == 0) {
                                gap++;
                            }
                        }
                        isContinue = true;
                        isLenthEnd = false;

                        for(i = 0; i <= 4 && pointX - i > 0 && pointY + i <= boardSize; i++){ //向左下检查
                            if (forecastChessboard[pointX-i][pointY+i] == color) {
                                colorNumber++;
                                if (i == 4) {
                                    lenth += 4;
                                    if (pointX - i - 1 > 0 && pointY + i + 1 <= boardSize
                                            && forecastChessboard[pointX-i - 1][pointY+i + 1] == 0){
                                        right = true;
                                    }
                                }
                                if (isContinue) {
                                    contiue++;
                                }
                            }else if (forecastChessboard[pointX-i][pointY+i] == 0) {
                                blank++;
                                isContinue = false;
                                if (pointX-i - 1 <= 0 || pointY + i + 1 > 15) {  //边界情况
                                    right = true;
                                    if (!isLenthEnd) {
                                        lenth += i - 1;
                                    }
                                    break;
                                }
                                if (forecastChessboard[pointX-i -1][pointY+i + 1] != color) {
                                    right = true;
                                    if (forecastChessboard[pointX - i - 2][pointY+i + 2] != color || i + 2 > 4){
                                        if (!isLenthEnd) {
                                            isLenthEnd = true;
                                            lenth += i - 1;
                                        }
                                    }
                                }
                            } else if (forecastChessboard[pointX-i][pointY+i] == 3 - color) {
                                lenth += i - 1;
                                break;
                            }
                        }
                        for (i = 1; i < lenth - tempLenth; i++) {
                            if (forecastChessboard[pointX-i][pointY+i] == 0) {
                                gap++;
                            }
                        }
                        setChessPointStyle(color, pointX, pointY, 3, contiue - 1, colorNumber - 1, blank, gap, lenth, left, right);

                        forecastChessboard[pointX][pointY] = 0;
                    }
                }

            }
        }
    }

    public void setChessPointStyle(int color, int pointX, int pointY, int dir,
                                   int contiue, int colorNumber, int blank, int gap, int lenth, boolean left, boolean right) {
        if (color == nowPlayer) {

            if (contiue >= 5 ) { 					       //1成五
                chessPointStyle[color][pointX][pointY][dir] = 100000;

            } else if (contiue == 4
                    && ((left && right) || (lenth >= 6 && colorNumber >= 5 && gap >= 1)) ) {  //2活四
                chessPointStyle[color][pointX][pointY][dir] = 5000;
            } else if (gap <= 1 && colorNumber >= 4 && blank >= 1
                    &&((left^right) || (left && right))){    //3冲四
                chessPointStyle[color][pointX][pointY][dir] = 2100;

            } else if (contiue == 3
                    && ((left && right) || (lenth >= 5 && colorNumber >= 4 && gap >= 1)) ){    //4连活三
                chessPointStyle[color][pointX][pointY][dir] = 1800;
            } else if (gap <= 1 && colorNumber >= 3 && left && right){    //5跳活三
                chessPointStyle[color][pointX][pointY][dir] = 1200;
            } else if (contiue == 3 && blank >= 2 && (left^right) ){    //6眠三
                chessPointStyle[color][pointX][pointY][dir] = 600;

            } else if (contiue == 2 && blank >= 3 && left && right){    //7连活二
                chessPointStyle[color][pointX][pointY][dir] = 300;
            } else if (gap <= 2 && colorNumber >= 2 && blank >= 3 && left && right){    //8(大)跳活二
                chessPointStyle[color][pointX][pointY][dir] = 230;
            } else if (contiue == 2 && blank >= 3 && (left^right) ){    //9眠二
                chessPointStyle[color][pointX][pointY][dir] = 100;

            } else if (contiue == 1 && blank >= 4 && left && right){    //10活一
                chessPointStyle[color][pointX][pointY][dir] = 50;
            } else if (contiue == 1 && blank >= 1 && (left^right) ){    //11眠一
                chessPointStyle[color][pointX][pointY][dir] = 15;
            }
        } else if (color == 3 - nowPlayer){

            if (contiue >= 5 ) { 					       //1成五
                chessPointStyle[color][pointX][pointY][dir] = 10000;

            } else if (contiue == 4
                    && ((left && right) || (lenth >= 6 && colorNumber >= 5 && gap >= 1)) ) {  //2活四
                chessPointStyle[color][pointX][pointY][dir] = 3000;
            } else if (gap <= 2 && colorNumber >= 4 && blank >= 1
                    &&((left^right) || (left && right))){    //3冲四
                chessPointStyle[color][pointX][pointY][dir] = 1800;

            } else if (contiue == 3
                    && ((left && right) || (lenth >= 5 && colorNumber >= 4 && gap >= 1)) ){    //4连活三
                chessPointStyle[color][pointX][pointY][dir] = 1200;
            } else if (gap <= 1 && colorNumber >= 3 && left && right){     //5(大)跳活三
                chessPointStyle[color][pointX][pointY][dir] = 1000;
            } else if (contiue == 3 && blank >= 2 && (left^right) ){    //6眠三
                chessPointStyle[color][pointX][pointY][dir] = 480;

            } else if (contiue == 2 && blank >= 3 && left && right){    //7连活二
                chessPointStyle[color][pointX][pointY][dir] = 240;
            } else if (gap <= 2 && colorNumber >= 2 && blank >= 3 && left && right){   //8(大)跳活二
                chessPointStyle[color][pointX][pointY][dir] = 200;
            } else if (contiue == 2 && blank >= 3 && (left^right) ){    //9眠二
                chessPointStyle[color][pointX][pointY][dir] = 80;

            } else if (contiue == 1 && blank >= 4 && left && right){    //10活一
                chessPointStyle[color][pointX][pointY][dir] = 40;
            } else if (contiue == 1 && blank >= 1 && (left^right) ){    //11眠一
                chessPointStyle[color][pointX][pointY][dir] = 10;
            }
        } else {
            System.err.println("setChessPointStyle error");
        }
    }


    public void setScope() {
        scope[1] = scope[2] = 15;  //初始化搜索框四边坐标
        scope[3] = scope[4] = 1;
        isCompute = new boolean[boardSize + 5][boardSize + 5];
        for (ChessPoint tempChessStack : chessStack) {   //棋盘已经落子的范围
            int X = tempChessStack.getX();
            int Y = tempChessStack.getY();
            for (int i = X - 2; i <= X + 2; i++) {
                if (i <= 0) continue;
                for (int j = Y - 2; j <= Y + 2; j++) {
                    if (j <= 0) continue;
                        isCompute[i][j] = true;
                }
            }
            if (X < scope[1]) scope[1] = X;
            if (X > scope[3]) scope[3] = X;
            if (Y < scope[2]) scope[2] = Y;
            if (Y > scope[4]) scope[4] = Y;
        }
        for (int j = 1; j <= 2; j++) {
            for (int i = 1; i <= 2; i++) {
                if (scope[i] - 1 > 0) {
                    scope[i]--;
                }
            }
            for (int i = 3; i <= 4; i++) {
                if (scope[i] + 1 <= 15){
                    scope[i]++;
                }
            }
        }
    }
}
